#pragma once
#include "stdafx.h"

#include <string>
using namespace std;

#include <gdiplus.h>
#pragma comment (lib,"Gdiplus.lib")
using namespace Gdiplus;

#define EM_ACTIVE (WM_USER+100)
typedef CWinTraits<WS_EX_LAYERED|WS_CHILDWINDOW> CLayerdWin;
class CDragableWin : public CWindowImpl<CDragableWin, CWindow, CLayerdWin>
{
protected:
	bool m_capture = false;
	bool m_drawConor = false;
	bool m_leftMouseButtonDown = false;

	Point m_startPos, m_curPos, m_bmpLeftTop;
	COLORREF m_borderColor = RGB(0,0,0), m_bgColor=RGB(0x33,0x33,0x33);

	CBrush m_bgBrush;

	int m_insideConor = -1;
	Pen m_cornorPen = (Color(255, 0x00,0x00,0xFF));
	Rect m_cornorRects[4];
	string m_text = "drag me";
public:
	BEGIN_MSG_MAP(CDragableWin)
		MESSAGE_HANDLER(WM_CREATE, OnCreate)

		MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActive)

		MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
		MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
		MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
		
		MESSAGE_HANDLER(WM_PAINT, OnPaint)
		MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
		MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)

		DEFAULT_REFLECTION_HANDLER()
	END_MSG_MAP()


	LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		m_bgBrush.CreateSolidBrush(RGB(255, 99, 71));
		SetLayeredWindowAttributes(m_hWnd, NULL, 185, LWA_ALPHA); // Tomato
		SetClassLong(m_hWnd, GCL_HBRBACKGROUND, (LONG)m_bgBrush.m_hBrush);
		return 0;
	}

	LRESULT OnMouseActive(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
	{
		m_drawConor = true;
		::SendMessage(GetParent().m_hWnd, EM_ACTIVE, (WPARAM)m_hWnd, 0);
		Invalidate();
		UpdateWindow();
		return 0;
	}

	void Deactivate() {
		m_drawConor = false;
		Invalidate();
		UpdateWindow();
	}

	LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
	{
		RECT rc;
		GetClientRect(&rc);
		m_cornorRects[0] = { 0, 0, 4, 4 };
		m_cornorRects[1] = { rc.right - 5, 0, 4, 4 };
		m_cornorRects[2] = { rc.right - 5, rc.bottom - 5, 4, 4 };
		m_cornorRects[3] = { 0, rc.bottom - 5, 4, 4 };
		
		POINT p = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
		LPCTSTR cursors[4] = { IDC_SIZENWSE, IDC_SIZENESW, IDC_SIZENWSE, IDC_SIZENESW };
		for (int i = 0; i < 4; i++) {
			if (m_cornorRects[i].Contains(Point{ p.x, p.y })) {
				SetCursor(LoadCursor(NULL, cursors[i]));
				break;
			}
		}
		if (m_insideConor >= 0) {
			m_leftMouseButtonDown = true;
			SetCapture();
		} else {
			//drag and move
			SendMessage(m_hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
		}
		return 0;
	}

	LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
	{
		m_leftMouseButtonDown = false;
		ReleaseCapture();
		return 0;
	}


	LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
	{
		RECT rc;
		GetClientRect(&rc);
		m_cornorRects[0] = { 0, 0, 4, 4 };
		m_cornorRects[1] = { rc.right - 5, 0, 4, 4 };
		m_cornorRects[2] = { rc.right - 5, rc.bottom - 5, 4, 4 };
		m_cornorRects[3] = { 0, rc.bottom - 5, 4, 4 };

		if (!m_leftMouseButtonDown) {
			m_insideConor = -1;
			Point p(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
			LPCTSTR cursors[4] = { IDC_SIZENWSE, IDC_SIZENESW, IDC_SIZENWSE, IDC_SIZENESW };
			for (int i = 0; i < 4; i++) {
				if (m_cornorRects[i].Contains(p)) {
					SetCursor(LoadCursor(NULL, cursors[i]));
					m_insideConor = i;
					break;
				}
			}
		} 
		
		if (m_leftMouseButtonDown && m_insideConor>=0) {
			POINT p = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
			RECT rc;
			GetClientRect(&rc);
			MapWindowPoints(GetParent().m_hWnd, &p, 1);
			MapWindowPoints(GetParent().m_hWnd, &rc);
		
			switch (m_insideConor) {
			case 0:
				rc.left = p.x, rc.top = p.y;
				break;
			case 1:
				rc.right = p.x; rc.top = p.y;
				break;
			case 2:
				rc.right = p.x; rc.bottom = p.y;
				break;
			case 3:
				rc.left = p.x; rc.bottom = p.y;
				break;
			}

			MoveWindow(&rc, TRUE);
			Invalidate();
			UpdateWindow();
		}
		return 0;
	}


	LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		//HDC hdc = (HDC)wParam;
		//RECT rc;
		//GetClientRect(&rc);
		//SetBkMode(hdc, TRANSPARENT);
		//Graphics g(hdc);
		//SolidBrush    white(Color(255, 255, 255,255));
		//g.FillRectangle(&white, GpRect{ rc.left,rc.top, rc.right - rc.left, rc.bottom - rc.top });
		//SolidBrush    brush(Color(100, GetRValue(m_bgColor), GetGValue(m_bgColor), GetBValue(m_bgColor)));
		//g.FillRectangle(&brush, GpRect{ rc.left,rc.top, rc.right - rc.left, rc.bottom - rc.top });
		////::FillRect(hdc, &rc, (HBRUSH)(COLOR_WINDOW));
		HDC hdc = (HDC)wParam;
		SetBkMode(hdc, TRANSPARENT);
		SetBkColor(hdc, TRANSPARENT);

		return 1;
	}

	LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
	{
		PAINTSTRUCT ps;
		HDC hdc = BeginPaint(&ps);

		////erase background
		FillRect(hdc, &ps.rcPaint, m_bgBrush);

		RECT rc;
		GetClientRect(&rc);

		SIZE size;
		GetTextExtentPoint32A(hdc, m_text.c_str(), m_text.size(), &size);
		SetBkMode(hdc, TRANSPARENT);
		::TextOutA(hdc, (rc.right-size.cx)/2, (rc.bottom-size.cy)/2, m_text.c_str(), m_text.size());

		if (m_drawConor) {
			Graphics g(hdc);
			
			SolidBrush    brush(Color(255, 255, 255, 255));
			RECT rc;
			GetClientRect(&rc);
			m_cornorRects[0] = { 0, 0, 4, 4 };
			m_cornorRects[1] = { rc.right - 5, 0, 4, 4 };
			m_cornorRects[2] = { rc.right - 5, rc.bottom - 5, 4, 4 };
			m_cornorRects[3] = { 0, rc.bottom - 5, 4, 4 };
			for (int i = 0; i < 4; i++) {
				g.DrawRectangle(&m_cornorPen, m_cornorRects[i]);
				//g.FillRectangle(&brush, cornors[i]);
			}
		}
		
		//dc.SelectBrush(hOldBrush);
		//dc.Detach();
		EndPaint(&ps);
		return 0;
	}



	LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{
		return 0;
	}
};